import asyncio
import logging
from json import JSONDecodeError

from aiogram.client.session.aiohttp import ClientSession
from aiohttp import ClientProxyConnectionError, ClientTimeout, ServerDisconnectedError
from aiohttp_proxy import ProxyConnector

from src.application.proxy.dto.proxy import ProxyDTO
from src.infrastructure.db.models import Proxy

logger = logging.getLogger(__name__)


async def get_proxy_status(proxy: ProxyDTO) -> tuple[bool, str] | tuple[bool, None]:
    url = "http://api.sypexgeo.net/json/"
    proxy_string = f"http://{proxy.login}:{proxy.password}@{proxy.server.ip_address}:{proxy.port_https}"
    try:
        connector = ProxyConnector.from_url(proxy_string)
        headers = {
            "Content-Type": "application/json; charset=UTF-8",
            "User-agent": "Mozilla/5.0 (Windows NT 11.0; Win64; rv:117.0esr) Gecko/20110101 Firefox/117.0esr/fMrqk1K7ra2",
        }
        async with ClientSession(connector=connector, headers=headers, timeout=ClientTimeout(total=17)) as session:
            async with session.get(url, verify_ssl=False) as req_:
                try:
                    res = await req_.json(content_type=None)
                except (TypeError, JSONDecodeError):
                    res = await req_.content.read()
                    logger.info(
                        f"Ошибка декодирования JSON для прокси {proxy_string} с сервера №{proxy.server_id}. Ответ сервера: {req_.status}. Контент: {res}"
                    )

                if (
                    req_.status == 502
                    or req_.status == 403
                    or "502 Bad Gateway" in str(res)
                    or "ervice unavailable" in str(res)
                    or "403 Forbidden" in str(res)
                    or "balance.beeline" in str(res)
                ):
                    txt = f"Невалидный прокси {proxy_string} с сервера №{proxy.server_id}"
                    return False, txt

                elif (
                    "заблокирован" in str(res)
                    or "unable" in str(res)
                    or "balance" in str(res)
                    or "portal.ncnd.vodafone" in str(res)
                ):
                    txt = f"Нет баланса на прокси {proxy_string} с сервера №{proxy.server_id}"
                    return False, txt

                elif req_.status == 407 or "407 proxy authentication required" in str(res):
                    txt = f"Неверный пароль для прокси {proxy_string} с сервера №{proxy.server_id}"
                    return False, txt

                logger.info(f"Прокси {proxy_string} валидный")
                return True, None

    except (
        asyncio.TimeoutError,
        ConnectionRefusedError,
        ServerDisconnectedError,
        ClientProxyConnectionError,
    ):
        txt = f"Не могу подключиться к прокси {proxy_string} с сервера №{proxy.server_id}"
        return False, txt
